import * as THREE from 'three'
import { on } from '../../utils/EventBus.js'
import { MapControls } from 'three/addons/controls/MapControls.js'
import { Player } from './Player.js'
import {
    ThreeScene,
    THREE_SCENE_INITIALIZATION,
} from '../../components/three/ThreeScene.js'

import { AssetManager } from './AssetManager.js'

export const group = new THREE.Group()

export const sceneName = 'threeScene'
import { Physics, MyCharacterController } from './Physics.js'

import { AssetContainer } from './AssetContainer.js'
import { Interval } from '../../components/three/utils/Interval.js'

class World {
    constructor(onLoad) {
        this.interval = new Interval()
        // this.physics = new Physics()
        // this.graphics
        // this.assets = new AssetLoader(this.onLoad.bind(this, onLoad))
    }
}

on(THREE_SCENE_INITIALIZATION, async ({ detail: t3Name }) => {
    if (sceneName !== t3Name) return

    const am = new AssetManager(onLoad)

    const threeScene = ThreeScene.getInstance(sceneName)

    const physics = new Physics()

    const mcc = new MyCharacterController(physics)

    const { camera, renderer, scene } = threeScene

    camera.position.set(120, 120, 120)

    const interval = new Interval()
    const mapControls = new MapControls(camera, renderer.domElement)
    mapControls.maxPolarAngle = Math.PI/2

    const player = new Player(camera)

    const level1 = {
        model: ['glb_0'],
        textures: ['texture_0'],
    }
    function loadLevel() {
        level1.model.forEach((id) => {
            const model = AssetContainer.instance.get(id)
            model.traverse((child) => {
                if (child.isMesh) {
                    child.userData.physics = {
                        mass: 0,
                        restitution: 1.0,
                    }
                }
            })
            const g1 = moveToOrigin(model)
            scene.add(g1)

            physics.addScene(scene)
        })
        level1.textures.forEach((id) => {
            const texture = AssetContainer.instance.get(id)
            if (texture) {
                texture.mapping = THREE.EquirectangularReflectionMapping
                scene.background = new THREE.Color(0x000000)
                scene.environment = texture
            }
        })
    }

    function onLoad() {
        createGround()

        interval.add((loop) => {
            threeScene.render(loop)
        })
        interval.start()
        loadLevel()

        const physicsStep = (state) => {
            let { delta } = state
            const isGrounded = mcc.characterController.computedGrounded()

            delta = (delta * 1.0) / 1000
            // delta = Math.min(0.05, delta) // STEPS_PER_FRAME
            // controls(delta, isGrounded)
            // const tr = getWill(delta, isGrounded)
            const tr = player.getTranslation(delta, isGrounded)
            mcc.testCollision(tr, (pos) => {
                camera.position.x = pos.x
                camera.position.y = pos.y
                camera.position.z = pos.z
            })
        }

        on('collision', ({ detail }) => {
            if (detail) {
                interval.add(physicsStep)
            } else {
                interval.remove(1, 1)
            }
        })
    }

    function createGround() {
        const ground = new THREE.Mesh(
            new THREE.BoxGeometry(500, 300, 0.2),
            // new THREE.MeshPhongMaterial({ color: 0xa0adaf, shininess: 150 })
            new THREE.MeshStandardMaterial({
                color: 0x666666,
                shininess: 0,
            })
        )
        ground.userData.physics = { mass: 0, restitution: 0 }
        ground.rotation.x = -Math.PI / 2 // rotates X/Y to X/Z
        ground.position.set(0, -0.5, 0)
        ground.receiveShadow = true
        scene.add(ground)
        // physics.addScene(ground)
    }

    /*
  function beginRotate(radius) {
    return (angle) => {
      angle /= 5000
      // const radius = 10 // 调整旋转半径
      camera.position.x = radius * Math.sin(angle)
      camera.position.z = radius * Math.cos(angle)
      camera.lookAt(0, 0, 0) // 确保相机始终看向目标点

      // renderer.render(scene, camera)
    }
  }

    */
    function moveToOrigin(object) {
        // Create a bounding box for the object
        const boundingBox = new THREE.Box3().setFromObject(object)

        // // Calculate the center of the bounding box
        const center = boundingBox.getCenter(new THREE.Vector3())
        center.y = boundingBox.min.y

        // Create a group to hold the model
        const group = new THREE.Group()
        group.aabb = boundingBox

        // Add the model to the group
        group.add(object)
        window.threeScene.tempCenter = center

        // Move the group so the model's center is at the origin
        group.position.sub(center)

        return group
    }
})
